package eu.chargetime.ocpp.jsonserverimplementation.server.impl;

import cn.hutool.json.JSONUtil;
import eu.chargetime.ocpp.JSONServer;
import eu.chargetime.ocpp.NotConnectedException;
import eu.chargetime.ocpp.ServerEvents;
import eu.chargetime.ocpp.jsonserverimplementation.common.Pair;
import eu.chargetime.ocpp.jsonserverimplementation.config.ApplicationConfiguration;
import eu.chargetime.ocpp.model.Confirmation;
import eu.chargetime.ocpp.model.Request;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@AllArgsConstructor
public class JsonServerImpl {

    private final ServerEvents serverEvents;
    private final JSONServer server;
    private final ApplicationConfiguration applicationConfiguration;



    @PostConstruct
    public void startServer() throws Exception {
        server.open("localhost", applicationConfiguration.getServerOcpp(), serverEvents);
        log.info("[startServer],port:{}", applicationConfiguration.getServerOcpp());
    }

    public Confirmation send(UUID sessionIndex, Request request) {
        try {
            log.info("[send] begin,sessionIndex:{},request:{}",sessionIndex.toString(), JSONUtil.toJsonStr(request));
            CountDownLatch downLatch = new CountDownLatch(1);
            Pair<Confirmation, Throwable> sendResponse = new Pair<>();
            server.send(sessionIndex, request).whenComplete((confirmation, throwable) -> {
                sendResponse.setLeft(confirmation);
                sendResponse.setRight(throwable);
                downLatch.countDown();
            });
            boolean await = downLatch.await(20, TimeUnit.SECONDS);
            log.info("[send] end,await:{},sessionIndex:{},request:{}",await,sessionIndex.toString(), JSONUtil.toJsonStr(request));
            if (await) {
                Throwable throwable = sendResponse.getRight();
                if (throwable != null) {
                    log.error("设备返回异常消息:" + throwable.getMessage(), throwable);
                } else {
                    return sendResponse.getLeft();
                }
            }
        } catch (NotConnectedException e) {
            log.error("设备不在线:" + e.getMessage(), e);
        } catch (InterruptedException e) {
            log.error("发送消息超时:" + e.getMessage(), e);
        } catch (Throwable e) {
            log.error("发送消息到设备异常:" + e.getMessage(), e);
        }
        return null;
    }


}
